<?php
// +----------------------------------------------------------------------
// | snake
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2022 http://baiyf.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: NickBai <1902822973@qq.com>
// +----------------------------------------------------------------------
namespace app\common\logic;

use think\Db;
use Flc\Dysms\Client;
use Flc\Dysms\Request\SendSms;

class SmsLogic extends BaseLogic
{
    private $isTest = true;
    private $config = [
        'accessKeyId'    => '',
        'accessKeySecret' => '',
        'signName' => '',
        'TemplateCode_Vcode' => '',//验证码模板
    ];
    public function __construct($projectId){
        parent::__construct('SmsLog');
        $configs = $this->_getSiteConfigAllList($projectId);
        $this->config['accessKeyId'] = $configs['site_sms_access_key_id'];
        $this->config['accessKeySecret'] = $configs['site_sms_access_key_secret'];
        $this->config['signName'] = $configs['site_sms_sign_name'];
        $this->config['TemplateCode_Vcode'] = $configs['site_sms_template_code_vcode'];
    }

    /**
     * 检测 是否符合发送
     * @param $phone
     * @return array
     */
    private function checkSendTimeIsOkByPhone($phone){
        if (true == $this->isTest) {
            return $this->retSuccess();
        }
        if(empty($phone)){
            return $this->retError('手机号码不能为空');
        }
        if(!isMobilePhone($phone)){
            return $this->retError('手机号码格式不正确');
        }
        $sms_send_interval = config('site.sms_send_interval');
        $where[] = ['phone','=',$phone];
        $where[] = ['create_time','>',(time() - ($sms_send_interval + 1))];
        // 如果 小于 1 说明 可以发送，大于0 说明不能发送
        if(Db::name('SmsLog')->where($where)->count() > 0){
            return $this->retError('发送太频繁，请稍后再重试！');
        }
    }

    /**
     * 发送验证短信
     * @param $phone
     * @return array
     * @throws \Exception
     */
    public function sendVcode($phone){
        $vcode = random(6,'number');
        $send_data['code'] = $vcode;
        return $this->alismsSend($phone, $send_data, $this->config['TemplateCode_Vcode']);
    }

    /**
     * 阿里云短信发送
     * @param $phone string 手机号码
     * @param $sendData array 发送数据
     * @param $templateCode string 短信模板CODE
     * @param string $signName string 签名，如果为传默认读取系统设置
     * @param int $handleId int 发送人
     * @return array
     * @throws \Exception
     */
    public function alismsSend($phone,$sendData,$templateCode,$signName = '',$handleId = 0){
        if(empty($signName)){
            $signName = $this->config['signName'];
        }
        // 检测 是否符合发送
        $checkJieguo = $this->checkSendTimeIsOkByPhone($phone);
        if($checkJieguo['err_code'] != 0){
            return $checkJieguo;
        }
        $client  = new Client($this->config);
        $sendSms = new SendSms;
        $sendSms->setPhoneNumbers($phone);
        $sendSms->setSignName($signName);
        $sendSms->setTemplateCode($templateCode);
        $sendSms->setTemplateParam($sendData);
        $sendSms->setOutId('gdbase');

        if (true == $this->isTest) {
            $jieguo = [
                'Message' => 'OK',
                'RequestId' => '864A3860-AB83-4520-8AFE-FCE34851491D',
                'BizId' => '269408809533351438^0',
                'Code' => 'OK',
            ];
        }
        else{
            $jieguo = $client->execute($sendSms);
            // 处理 返回 转换成数组
            $tmp = json_encode($jieguo, 256);
            $jieguo = json_decode($tmp, true);
        }
        if('OK' != $jieguo['Code']){
            return $this->retError('发送错误，请联系管理员！');
        }
        // 写入日志
        $this->save([
            'id' => 0,
            'supplier' => 'alisms',
            'phone' => $phone,
            'send_data' => json_encode($sendData,256),
            'template_id' => $templateCode,
            'sign_name' => $signName,
            'handle_id' => $handleId,
            'return_data' => json_encode($jieguo,256),
            'create_time' => time(),
        ]);

        if (true == $this->isTest) {
            return $this->retSuccess('测试 短信已经发送，请注意查收！',$sendData);
        }
        else{
            return $this->retSuccess('短信已经发送，请注意查收！');
        }
    }

    /**
     * 检测短信验证码是否正确
     * @param $phone
     * @param $vcode
     * @return array
     * @throws \Exception
     */
    public function checkVCode($phone,$vcode){
        $slModel = Db::name('SmsLog')->where('phone',$phone)->order('create_time DESC')->find();
        if(empty($slModel)){
            return $this->retError('请先发送短信验证码');
        }
        $sendData = $slModel['send_data'];
        if(empty($sendData)){
            return $this->retError('找不到发送数据');
        }
        $json = json_decode($sendData, true);
        if(empty($json)){
            exception('解析发送数据出错！');
        }
        if(empty($json['code'])){
            exception('发送数据不包含 code ！');
        }
        if($json['code'] == $vcode){
            // 验证时间
            $timeout = 600;
            if (!($slModel['create_time'] + $timeout > time())) {
                // 过期
                return $this->retError('验证码过期了，请重新获取');
            }
            else{
                return $this->retSuccess('短信验证码，验证通过');
            }
        }
        else{
            return $this->retError('短信验证码，验证不通过');
        }
    }
}